package com.governtalk.backend.service.impl;

import com.governtalk.backend.dto.group.StudyGroupDto;
import com.governtalk.backend.entity.StudyGroup;
import com.governtalk.backend.entity.User;
import com.governtalk.backend.entity.GroupMember;
import com.governtalk.backend.repository.StudyGroupRepository;
import com.governtalk.backend.repository.GroupMemberRepository;
import com.governtalk.backend.repository.UserRepository;
import com.governtalk.backend.service.StudyGroupService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Transactional
public class StudyGroupServiceImpl implements StudyGroupService {
    
    @Autowired
    private StudyGroupRepository studyGroupRepository;
    
    @Autowired
    private GroupMemberRepository groupMemberRepository;
    
    @Autowired
    private UserRepository userRepository;
    
    @Override
    public Page<StudyGroupDto> getAllGroups(Pageable pageable) {
        Page<StudyGroup> groups = studyGroupRepository.findByIsPublicTrueAndIsActiveTrue(pageable);
        return groups.map(this::convertToDto);
    }
    
    @Override
    public Page<StudyGroupDto> getGroupsByCategory(Long categoryId, Pageable pageable) {
        Page<StudyGroup> groups = studyGroupRepository.findByCategoryIdAndIsPublicTrueAndIsActiveTrue(categoryId, pageable);
        return groups.map(this::convertToDto);
    }
    
    @Override
    public Page<StudyGroupDto> searchGroups(String keyword, Pageable pageable) {
        Page<StudyGroup> groups = studyGroupRepository.searchGroups(keyword, pageable);
        return groups.map(this::convertToDto);
    }
    
    @Override
    public Page<StudyGroupDto> getPopularGroups(Pageable pageable) {
        Page<StudyGroup> groups = studyGroupRepository.findPopularGroups(pageable);
        return groups.map(this::convertToDto);
    }
    
    @Override
    public Page<StudyGroupDto> getLatestGroups(Pageable pageable) {
        Page<StudyGroup> groups = studyGroupRepository.findLatestGroups(pageable);
        return groups.map(this::convertToDto);
    }
    
    @Override
    public StudyGroupDto getGroupById(Long groupId) {
        StudyGroup group = studyGroupRepository.findById(groupId)
                .orElseThrow(() -> new RuntimeException("Group not found"));
        return convertToDto(group);
    }
    
    @Override
    public StudyGroupDto createGroup(StudyGroupDto groupDto) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        User creator = userRepository.findByUsername(username)
                .orElseThrow(() -> new RuntimeException("User not found"));
        
        StudyGroup group = StudyGroup.builder()
                .name(groupDto.getName())
                .description(groupDto.getDescription())
                .creator(creator)
                .categoryId(groupDto.getCategoryId())
                .maxMembers(groupDto.getMaxMembers())
                .currentMembers(1)
                .isPublic(groupDto.getIsPublic())
                .isActive(true)
                .build();
        
        StudyGroup savedGroup = studyGroupRepository.save(group);
        
        // 创建者自动成为管理员
        GroupMember adminMember = GroupMember.builder()
                .group(savedGroup)
                .user(creator)
                .role(GroupMember.GroupRole.ADMIN)
                .joinedAt(LocalDateTime.now())
                .status(GroupMember.GroupMemberStatus.ACTIVE)
                .build();
        
        groupMemberRepository.save(adminMember);
        
        return convertToDto(savedGroup);
    }
    
    @Override
    public StudyGroupDto updateGroup(Long groupId, StudyGroupDto groupDto) {
        StudyGroup group = studyGroupRepository.findById(groupId)
                .orElseThrow(() -> new RuntimeException("Group not found"));
        
        // 检查权限
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        User currentUser = userRepository.findByUsername(username)
                .orElseThrow(() -> new RuntimeException("User not found"));
        
        if (!group.getCreator().getId().equals(currentUser.getId())) {
            throw new RuntimeException("No permission to update this group");
        }
        
        group.setName(groupDto.getName());
        group.setDescription(groupDto.getDescription());
        group.setCategoryId(groupDto.getCategoryId());
        group.setMaxMembers(groupDto.getMaxMembers());
        group.setIsPublic(groupDto.getIsPublic());
        
        StudyGroup savedGroup = studyGroupRepository.save(group);
        return convertToDto(savedGroup);
    }
    
    @Override
    public void deleteGroup(Long groupId) {
        StudyGroup group = studyGroupRepository.findById(groupId)
                .orElseThrow(() -> new RuntimeException("Group not found"));
        
        // 检查权限
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        User currentUser = userRepository.findByUsername(username)
                .orElseThrow(() -> new RuntimeException("User not found"));
        
        if (!group.getCreator().getId().equals(currentUser.getId())) {
            throw new RuntimeException("No permission to delete this group");
        }
        
        group.setIsActive(false);
        studyGroupRepository.save(group);
    }
    
    @Override
    public void joinGroup(Long groupId) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new RuntimeException("User not found"));
        
        StudyGroup group = studyGroupRepository.findById(groupId)
                .orElseThrow(() -> new RuntimeException("Group not found"));
        
        // 检查是否已加入
        if (groupMemberRepository.existsByGroupIdAndUserId(groupId, user.getId())) {
            throw new RuntimeException("Already joined this group");
        }
        
        // 检查小组是否已满
        if (group.getCurrentMembers() >= group.getMaxMembers()) {
            throw new RuntimeException("Group is full");
        }
        
        GroupMember member = GroupMember.builder()
                .group(group)
                .user(user)
                .role(GroupMember.GroupRole.MEMBER)
                .joinedAt(LocalDateTime.now())
                .status(GroupMember.GroupMemberStatus.ACTIVE)
                .build();
        
        groupMemberRepository.save(member);
        
        // 更新小组成员数
        group.setCurrentMembers(group.getCurrentMembers() + 1);
        studyGroupRepository.save(group);
    }
    
    @Override
    public void leaveGroup(Long groupId) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new RuntimeException("User not found"));
        
        GroupMember member = groupMemberRepository.findByGroupIdAndUserId(groupId, user.getId())
                .orElseThrow(() -> new RuntimeException("Not a member of this group"));
        
        groupMemberRepository.delete(member);
        
        // 更新小组成员数
        StudyGroup group = studyGroupRepository.findById(groupId)
                .orElseThrow(() -> new RuntimeException("Group not found"));
        group.setCurrentMembers(group.getCurrentMembers() - 1);
        studyGroupRepository.save(group);
    }
    
    @Override
    public List<StudyGroupDto> getUserGroups(Long userId) {
        List<StudyGroup> groups = studyGroupRepository.findGroupsByUserId(userId);
        return groups.stream().map(this::convertToDto).collect(Collectors.toList());
    }
    
    @Override
    public boolean isUserJoined(Long groupId, Long userId) {
        return groupMemberRepository.existsByGroupIdAndUserId(groupId, userId);
    }
    
    private StudyGroupDto convertToDto(StudyGroup group) {
        StudyGroupDto dto = StudyGroupDto.builder()
                .id(group.getId())
                .name(group.getName())
                .description(group.getDescription())
                .creatorId(group.getCreator().getId())
                .creatorName(group.getCreator().getNickname() != null ? group.getCreator().getNickname() : group.getCreator().getUsername())
                .creatorAvatar(group.getCreator().getAvatarUrl())
                .categoryId(group.getCategoryId())
                .maxMembers(group.getMaxMembers())
                .currentMembers(group.getCurrentMembers())
                .isPublic(group.getIsPublic())
                .isActive(group.getIsActive())
                .createdAt(group.getCreatedAt())
                .updatedAt(group.getUpdatedAt())
                .build();
        
        // 检查当前用户是否已加入
        try {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication != null && !"anonymousUser".equals(authentication.getName())) {
                String username = authentication.getName();
                User currentUser = userRepository.findByUsername(username).orElse(null);
                if (currentUser != null) {
                    dto.setIsJoined(isUserJoined(group.getId(), currentUser.getId()));
                }
            }
        } catch (Exception e) {
            // 忽略错误，设置为未加入
            dto.setIsJoined(false);
        }
        
        return dto;
    }
}

